﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace SmokinAces.Object_Classes
{
    //This is the generic class where the object get's registered.
    public class Quadtree
    {
        protected const int Division = 64;
        BoundingBox MapSize;
        List<QuadNode> Subdivisions = new List<QuadNode>();
        public Quadtree(BoundingBox Map_Size)
        {
            MapSize = Map_Size;
            float width = MapSize.Min.X + ((MapSize.Max.X - MapSize.Min.X) * 0.5f);
            float height = MapSize.Min.Y  + ((MapSize.Max.Y - MapSize.Min.Y) * 0.5f);
                Vector3 zerohd2 = new Vector3(MapSize.Min.X, height, MapSize.Min.Z);
                Vector3 wd2hd2min = new Vector3(width, height, MapSize.Min.Z);
                Vector3 wd2hd2max = new Vector3(width, height, MapSize.Max.Z);
                Vector3 wd2h = new Vector3(width, MapSize.Max.Y, MapSize.Max.Z);
                Vector3 whd2 = new Vector3(MapSize.Max.X, height, MapSize.Max.Z);
                Vector3 wd2zero = new Vector3(width, 0.0f, MapSize.Min.Z);
                QuadNode TL = new QuadNode(new BoundingBox(zerohd2, wd2h));
                QuadNode TR = new QuadNode(new BoundingBox(wd2hd2min, MapSize.Max));
                QuadNode BL = new QuadNode(new BoundingBox(MapSize.Min, wd2hd2max));
                QuadNode BR = new QuadNode(new BoundingBox(wd2zero, whd2));
                Subdivisions.Add(TL);
                Subdivisions.Add(TR);
                Subdivisions.Add(BL);
                Subdivisions.Add(BR);
        }
        public HashSet<Game_Object> Intersections(BoundingBox item)
        {
            HashSet<Game_Object> item_intersections = new HashSet<Game_Object>();
            if (MapSize.Intersects(item))
            {
                foreach (QuadNode iter in Subdivisions)
                {
                    foreach (Game_Object gObject in iter.Intersections(item))
                    {
                        item_intersections.Add(gObject);
                    }
                }
            }
            return item_intersections;
        }
        public void Add(Game_Object item)
        {
            foreach(QuadNode iter in Subdivisions)
            {
                iter.add(item);
            }
        }
        public void Remove(Game_Object item)
        {
            foreach (QuadNode iter in Subdivisions)
            {
                iter.remove(item);
            }
        }
        public HashSet<Game_Object> All_Objects()
        {
            HashSet<Game_Object> item_intersections = new HashSet<Game_Object>();
                foreach (QuadNode iter in Subdivisions)
                {
                    foreach (Game_Object gObject in iter.All_Objects())
                    {
                        item_intersections.Add(gObject);
                    }
                }
            return item_intersections;
        }
    }
    //This is more or less a helper class for the quadtree
    class QuadNode
    {
        BoundingBox Coords;
        HashSet<Game_Object> Containing_Objects = new HashSet<Game_Object>();
        Quadtree Subunits = null; //The Children of this node are defined here
        public QuadNode(BoundingBox Coordinates)
        {
            Coords = Coordinates;
            if (Coordinates.Max.X - Coordinates.Min.X > 128 && Coordinates.Max.Y - Coordinates.Min.Y > 128)
            {
                Subunits = new Quadtree(Coordinates);
            }
        }
        public HashSet<Game_Object> All_Objects()
        {
                return Containing_Objects;
        }
        public HashSet<Game_Object> Intersections(BoundingBox item)
        {
            if (Subunits == null)
            {
                return Containing_Objects;
            }
            else
            {
                return Subunits.Intersections(item);
            }
        }
        public void add(Game_Object item)
        {
            if (Coords.Intersects(item.GraphicBB))
            {
                Containing_Objects.Add(item);
                if (Subunits != null)
                {
                    Subunits.Add(item);
                }
            }
        }
        public void remove(Game_Object item)
        {
            if (Containing_Objects.Contains(item))
            {
                Containing_Objects.Remove(item);
                if (Subunits != null)
                {
                    Subunits.Remove(item);
                }
           } 
        }
    }
}




